hid: ipts: Fix double list_del race in ipts_mei_search() - #178
Open
joshuaspaulding wants to merge 1 commit into
Open
hid: ipts: Fix double list_del race in ipts_mei_search()#178joshuaspaulding wants to merge 1 commit into
joshuaspaulding wants to merge 1 commit into
Conversation
ipts_mei_search() looks up a matching response under the read side of message_lock, drops the lock, and then re-acquires it for writing to unlink the entry. Two concurrent callers waiting for the same command code (typically the receiver poll thread and a userspace hidraw raw request, both inside ipts_control_send_feedback()) can each find the same entry during their read-locked walk and then both unlink and free it. The second list_del() hits LIST_POISON and, with CONFIG_DEBUG_LIST, oopses the poll kthread: list_del corruption, ...->next is LIST_POISON1 (dead000000000100) kernel BUG at lib/list_debug.c:56! RIP: __list_del_entry_valid_or_report.cold Call Trace: ipts_mei_search+0x83/0x150 [ipts] ipts_mei_recv+0x61/0x190 [ipts] ipts_cmd_recv_timeout+0x2f/0x90 [ipts] ipts_control_send_feedback+0x81/0xc0 [ipts] ipts_receiver_poll_loop.cold+0x89/0x11c [ipts] ipts_thread_runner+0x21/0x40 [ipts] Without CONFIG_DEBUG_LIST the same race shows up as a general protection fault on 0xdead000000000108 in ipts_mei_search(). The other caller is then left blocked in D state inside the driver, which makes every later suspend fail with "tasks refusing to freeze". Seen on resume from s2idle on a Surface Pro 7 while iptsd was (re)started. Hold the write lock across the search and the unlink so that a message can only be claimed by one caller. Signed-off-by: Josh Spaulding <git@spaulding.app>
joshuaspaulding
force-pushed
the
ipts-fix-mei-search-race
branch
from
September 3, 2026 02:49
4d5bc29 to
f6df3e9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ipts_mei_search()walks the received-message list under the read side ofmessage_lock, drops the lock, then re-takes it for writing to unlink the entry it found. Two waiters for the same command code (typically the receiver poll thread and a userspace hidraw raw request, both insideipts_control_send_feedback()) can each find the same entry during their read-locked walk and then both unlink and free it. The secondlist_del()hitsLIST_POISONand, withCONFIG_DEBUG_LIST, oopses the poll kthread:Without
CONFIG_DEBUG_LISTit surfaces as a general protection fault on0xdead000000000108inipts_mei_search(). The other caller is then stuck in D state inside the driver, so every later suspend fails with "tasks refusing to freeze" until reboot.This is the same trace as linux-surface/linux-surface#2122 and linux-surface/intel-precise-touch#33.
The fix holds the write lock across the search and the unlink, so a message can only be claimed by one caller.
Testing
Surface Pro 7 (IPTS 045E:099F, EDS v2, poll mode). Reproduced on 6.12.107 with the stock patch series: oops on resume from s2idle while iptsd was being restarted, followed by an unfreezable iptsd for the rest of the boot. Rebuilt 6.12.107 with this change and ran repeated s2idle suspend/resume cycles with iptsd stopped before sleep and restarted on wake, which exercises the poll thread and the hidraw path concurrently. No oops, poll thread and iptsd healthy after every cycle.
The
drivers/hid/ipts/mei.cin this branch is identical to the 6.12 series version, so the patch applies unchanged across the maintained branches.